#!/usr/bin/python
#***************************************************************************
# Copyright notice for this file:
#  Copyright (C) 2012 TheAxeMan
#  _______ _                               _    _
# |__   __| |     ___     /\          ___ | \  / |
#    | |  | |__  / _ \   /  \  __  _ / _ \|  \/  | __ _ _ __
#    | |  | '_ \|  __/  / /\ \ \ \/ |  __/| .  . |/ _` | '_ \
#    | |  | | | | (__/\/ ____ \ )  (| (__/| |\/| | (_| | | | |
#    |_|  |_| |_|\____/_/    \_._/\_.\____|_|  |_|\__,_|_| |_|
#
# Final Fantasy TAS scripts by TheAxeMan
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
#***************************************************************************


from battlePlannerLib        import Combatant, BattleRandGenerator, CharType
from battlePlannerBattle     import Battle


class Pirate(Combatant):
  damage = 8
  defense = 0
  num_hits = 1
  crit_threshold = 1
  hit_threshold = 116
  type = CharType.pirate
  
class Lvl1Fighter(Combatant):
  damage = 10
  defense = 0
  num_hits = 1
  crit_threshold = 1
  hit_threshold = 166
  type = CharType.level1fighter

class Lvl2WhiteMageWithIronHammer(Combatant):
  damage = 12
  defense = 0
  num_hits = 1
  crit_threshold = 5
  hit_threshold = 162
  type = CharType.level2whitemage
  
class PiratesBattle(Battle):
  partyFightCost = 138
  dust_seeds = 54
  startingHeroHp = 28
  
  def __init__(self):
    '''Override to add the right combatants'''
    self.rand_engine = BattleRandGenerator()
    self.rand_engine.seed = 184
    
    self.enemy_list = [Pirate(6) for i in xrange(9)]
    #self.party_list = [Lvl1Fighter(35) for i in xrange(4)]
    self.party_list = [Lvl2WhiteMageWithIronHammer(28) for i in xrange(4)]
    self.party_list[3].hp = 0
    
    self.orderSeedCosts, self.orderFrameCosts = self.getOrderCosts()
    
  def getMaxWaitSeeds(self, roundNumber):
    if roundNumber >= 3:
      return 20
    #if roundNumber == 2:
      #return 20
    if roundNumber > 1:
      return 10
    return 10
  
  def firstCharGetsLuck(self):
    return self.rand_engine.seed in BattleRandGenerator.luckySeeds
  
  def secondCharGetsLuck(self):
    return (self.rand_engine.seed+1)%256 in BattleRandGenerator.luckySeeds
    
  def roundIsAcceptable(self, roundNumber, totalCost, roundDamage, enemyAttacks):
    #Aim for minimum number of rounds
    if roundNumber >= 3:
      return False
    #There is one more round to go, so cap cost below estimate
    #if totalCost > 2000:
    #  return False
    enemiesLiving = self.enemiesLiving()
    partyMembersLiving = self.partyMembersLiving()
    if roundNumber == 1:
      if partyMembersLiving < 3:
        return False
      #if enemiesLiving != 6 or enemyAttacks > 6:
      #if enemiesLiving != 6 or enemyAttacks > 7:
      if enemiesLiving != 6:
        return False
    if roundNumber == 2:
      if partyMembersLiving < 3:
        return False
      #if enemiesLiving != 3 or enemyAttacks > 3:
      #if enemiesLiving != 3 or enemyAttacks > 4:
      if enemiesLiving != 3:
        return False
    #if roundNumber == 3 and partyMembersLiving != 1:
        #return False
    return True

  def resultIsAcceptable(self, totalCost):
    if self.partyMembersLiving() != 2:
      return False
    if not self.secondCharGetsLuck():
      return False
    return True
  
  def getPossibleOrders(self, roundNumber):
    '''This generates all possibilities for the players attacking any enemy or running.
       Override to be smarter.'''
    #Someone could run on round 3
    #if roundNumber == 3:
      #possible_orders = Battle.getPossibleOrders(self, roundNumber)
      #return set(filter(lambda orders: list(orders).count(-1) < 3, possible_orders))
    
    #For pirates we will never use run
    all_single_orders = filter(lambda i: self.enemy_list[i].hp > 0, range(9))
    single_order = [ [-1] if self.party_list[i].hp == 0 else all_single_orders for i in xrange(4) ]
    
    #Also, don't have two people attack the same pirate
    possible_orders = set()
    for a in single_order[0]:
      bOrders = filter(lambda x: x!=a, single_order[1])
      for b in bOrders:
        cOrders = filter(lambda x: x not in [a,b], single_order[2])
        for c in cOrders:
          dOrders = filter(lambda x: x not in [a,b,c], single_order[3])
          for d in dOrders:
            possible_orders.add( (a,b,c,d) )
    return possible_orders
  

def setupBattle():
  BattleRandGenerator.populateBattleOrderLookupTable()
  BattleRandGenerator.populateTargetLookupTable()
  BattleRandGenerator.luckySeeds = BattleRandGenerator().luckRaiseSeeds()
  
  pirate = Pirate(6)
  whiteMage = Lvl2WhiteMageWithIronHammer(28)
  
  Lvl2WhiteMageWithIronHammer.populateDamageLookupTable(pirate)
  Pirate.populateDamageLookupTable(whiteMage)
  
  return PiratesBattle()

def pirate_demo():
  pirate_fight = setupBattle()
  
  order_list = []
  if 0:
    order_list.append([4,6,3,-1])
    order_list.append([2,8,0,-1])
    order_list.append([5,1,7,-1])
    wait_list = [0, 1, 0]
  if 1:
    order_list.append([5,6,4,-1])
    order_list.append([3,0,2,-1])
    order_list.append([1,7,8,-1])
    wait_list = [2, 19, 50]

  for i in xrange(len(wait_list)):
    pirate_fight.rand_engine.useUpRands(wait_list[i])

    roundCost, roundDamage, partyPerished, monstersPerished, enemyAttacks = \
             pirate_fight.simulateRound(order_list[i], print_attack=True)
    print "pirates attacked",enemyAttacks,"times"
    print "seed is",pirate_fight.rand_engine.seed
    print ""
    
def optimizePirates():
  pirate_fight = setupBattle()
  pirate_fight.optimize()
    
if __name__ == "__main__":
  #pirate_demo()  
  optimizePirates()  
  